﻿////////////////////////////////////////////////////////////////////////////////////////////////////
//
// VSCoverageToEmma - Visual Studio Coverage file to Emma converter
// Copyright (c) Kouji Matsui, All rights reserved.
//
// * Redistribution and use in source and binary forms, with or without modification,
//   are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
////////////////////////////////////////////////////////////////////////////////////////////////////

using System.Collections.Generic;
using System.Linq;
using System.Xml;

namespace VSCoverageToEmma.Analyzer.EmmaViews
{
	internal abstract class EmmaClassViewBase<T> : EmmaViewBase
		where T : EmmaViewBase
	{
		protected readonly Dictionary<string, T> children_ = new Dictionary<string, T>();

		protected EmmaClassViewBase(string name)
			: base(name)
		{
		}

		public abstract EmmaContains Classes
		{
			get;
		}

		public override EmmaContains Methods
		{
			get
			{
				return new EmmaContains(
					children_.Select(entry => entry.Value.Methods.ValidCount).Sum(),
					children_.Select(entry => entry.Value.Methods.TotalCount).Sum());
			}
		}

		public override EmmaContains Blocks
		{
			get
			{
				return new EmmaContains(
					children_.Select(entry => entry.Value.Blocks.ValidCount).Sum(),
					children_.Select(entry => entry.Value.Blocks.TotalCount).Sum());
			}
		}

		public override EmmaContains Lines
		{
			get
			{
				return new EmmaContains(
					children_.Select(entry => entry.Value.Lines.ValidCount).Sum(),
					children_.Select(entry => entry.Value.Lines.TotalCount).Sum());
			}
		}

		public T GetOrAdd(string name, Func<string, T> creator)
		{
			T child;
			if (children_.TryGetValue(name, out child) == false)
			{
				child = creator(name);
				children_.Add(child.Name, child);
			}

			return child;
		}

		protected override void WriteCoverageEntries(XmlWriter xw)
		{
			WriteCoverageEntry(xw, "class", this.Classes);
			base.WriteCoverageEntries(xw);
		}

		protected void WriteChildren(XmlWriter xw, string elementName)
		{
			foreach (var entry in children_.OrderBy(entry => entry.Key))
			{
				entry.Value.Write(xw, elementName);
			}
		}

		public override string ToString()
		{
			return string.Format("Classes={0}, {1}", this.Classes, base.ToString());
		}
	}
}
